package statistics;

import java.util.Random;

/**
 * This class represents a Poisson Distribution.
 */

public class PoissonDistribution extends DiscreteDistribution {

  private double lambda;

  /**
   * Constructs a Poisson Distribution with parameter lambda.
   * @param lambda the parameter of the Poisson Distribution with expectation lambda.
   */

  public PoissonDistribution(double lambda) {
    this.lambda = lambda;
    random = new Random();
  }

  /**
   * Constructs a Poisson Distribution with parameter lambda. You must also specify the
   * random seed that will be used to realize random variables with this distribution.
   * @param lambda the parameter of the Poisson Distribution with expectation lambda.
   * @param random the random seed.
   */

  public PoissonDistribution(double lambda, Random random) {
    this.lambda = lambda;
    this.random = random;
  }

  /**
   * Returns the expectation of a Poisson distribution with parameter lambda.
   */

  public double expectation() {
    return lambda;
  }

  /**
   * Returns the variance of a Poisson distribution with parameter lambda.
   */

  public double variance() {
    return lambda;
  }

  /**
   * Returns P(X = k), X is a Poisson distributed random variable.
   * @param k
   */

  public double probabilityFunction(int k) {
    if (k <= 0) return 0;
       else {
            double p = 1;
            for (int i = 1; i < k+1; i++) {
                p = p*(lambda/i);
            }//end for
            p = p*Math.exp(-lambda);
            return p;
       }//end else
  }

  /**
   * Returns a realization of a random variable with a Poisson distribution.
   */

  public double nextRandom() {
    double som = 0;
    int i = 0;
    Distribution dist = new ExponentialDistribution(1.0, random);
    while(som <= lambda) {
         double e = dist.nextRandom();
         som = som + e;
         i = i+1;
    }//end while
    return i-1;
  }
}
